package com.knightboy.smartshoes.core;

/**
 * Created by knightBoy on 2015/7/28.
 */
public class LocationHelper {
    //存储正在行走路段的长度，拐角方向，剩余长度，起点，终点
    public static double distance;     //最近那段路的长度
    public static int direction;       //最近那段路的终点转向
    public static double remain;       //最近那段路的剩余长度
    public static char fromPlace;      //最近那段路的起点
    public static char toPlace;        //最近那段路的终点
    public static char destination;    //最终的终点
    public static String axis;         //前进的轴向

    //定义无穷大
    private final static int INF = 65536;
    //存储的是地图上最近两点的直线距离
    private final static double[][] lengths = new double[][]{
            /*A*/ {0, 4.30, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF},
            /*B*/ {4.30, 0, 5.78,INF,7.27, INF, INF, INF, 1.82, INF, INF, INF, INF, INF, INF},
            /*C*/ {INF, 5.77, 0, 5.38,INF, INF, INF, INF, INF, 1.89, INF, INF, INF, 1.83, INF},
            /*D*/ {INF,INF, 5.83,0, INF,   INF, INF, INF, INF, INF, 1.80, INF, INF, INF,1.97},
            /*E*/ {INF,7.27,INF,INF, 0,    5.03,INF,2.02, INF, INF, INF, INF, 1.87, INF, INF},
            /*F*/ {INF,INF, INF,INF,5.03,  0,  1.75, INF, INF, INF, INF, 2.08, INF, INF, INF},
            /*G*/ {INF,INF,INF, INF, INF, 1.75,0,    INF, INF, INF, INF, INF, INF, INF, INF},
            /*H*/ {INF,INF,INF, INF, 2.02,INF,INF,0,  INF,INF, INF, INF, INF, INF, INF},
            /*I*/ {INF,1.82,INF, INF, INF, INF,INF,INF,0, INF, INF, INF, INF, INF, INF},
            /*J*/ {INF,INF,1.89, INF, INF, INF,INF,INF,INF, 0, INF, INF, INF, INF, INF},
            /*K*/ {INF,INF,INF, 1.80, INF, INF,INF,INF,INF, INF, 0, INF, INF, INF, INF},
            /*L*/ {INF,INF,INF, INF, INF, 2.08,INF,INF,INF, INF, INF, 0, INF, INF, INF},
            /*M*/ {INF,INF,INF, INF, 1.87, INF,INF,INF,INF, INF, INF, INF, 0, INF, INF},
            /*N*/ {INF,INF,1.83, INF, INF, INF,INF,INF,INF, INF, INF, INF, INF, 0, INF},
            /*O*/ {INF,INF,INF, 1.97, INF, INF,INF,INF,INF, INF, INF, INF, INF, INF, 0}};

    //存储的是地图上最近两点的方向
    private final static int[][] directions = new int[][]{
            /*A*/ {0,3,0,0,0,0,0,0,0,0,0,0,0,0,0},
            /*B*/ {1,0,4,0,2,0,0,0,3,0,0,0,0,0,0},
            /*C*/ {0,2,0,4,0,0,0,0,0,3,0,0,0,1,0},
            /*D*/ {0,0,2,0,0,0,0,0,0,0,3,0,0,0,1},
            /*E*/ {0,4,0,0,0,2,0,3,0,0,0,0,1,0,0},
            /*F*/ {0,0,0,0,4,0,3,0,0,0,0,1,0,0,0},
            /*G*/ {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},
            /*H*/ {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
            /*I*/ {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
            /*J*/ {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
            /*K*/ {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
            /*L*/ {0,0,0,0,0,3,0,0,0,0,0,0,0,0,0},
            /*M*/ {0,0,0,0,3,0,0,0,0,0,0,0,0,0,0},
            /*N*/ {0,0,3,0,0,0,0,0,0,0,0,0,0,0,0},
            /*O*/ {0,0,0,3,0,0,0,0,0,0,0,0,0,0,0}};

    //存储地图上点的坐标
    private final static String[] coordinates = new String[]{"1.27|3|-66.33","12.51|3|-69.99","12.12|3|-88.11",
            "11.67|3|-115.49","13.53|3|-37","14.55|3|-14.52","26.27|3|-15.07","24.9|3|-37.36","22.67|3|-66.33",
            "22.61|3|-90.35","23.31|3|-113.67","2.69|3|-13.98","1.11|3|-36.78","0.99|3|-90.35","0.829|3|-113.25"};
    //定义根据弗若伊德算法得出的计算结果。只要不关程序。一直有用
    private static int length = lengths[0].length;
    private static boolean isFirstTime = true;
    private static int[][] Path = new int[length][length];
    private static double[][] edgeLength = new double[length][length];

    /**
     * 根据坐标点返回代表点的坐标字符串
     * @param point 代表点的字符
     * @return
     */
    public static String getPoint(char point){
        return coordinates[point-65];
    }

    /**
     * 剩余路径的减少
     * @param aDistance
     */
    public static void reduceRemain(double aDistance){
        remain -= aDistance;
    }

    /**
     * 判断是否达到目的地
     * @return
     */
    public static boolean hasReach(){
        if(remain <= 0){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 开放给外界的接口
     * @param from
     * @param to
     */
    public static void getPath(char from, char to){
        //开始设置参数
        destination = to;
        //判断是否第一次调用，是的话，用弗若伊德算法计算出所有路径
        if(isFirstTime == true){
            Floyd(lengths);
            isFirstTime =false;
        }
        //获得最先的两个点
        int[] points = getTwoPoints(from-65,to-65);
        distance = remain = lengths[from-65][points[0]];
        fromPlace = from;
        toPlace = (char)(points[0] + 65);

        //计算应走的轴向
        int maxis = directions[from-65][points[0]];
        switch (maxis){
            case 1:
                axis = "-x";
                break;
            case 2:
                axis = "-z";
                break;
            case 3:
                axis = "x";
                break;
            case 4:
                axis = "z";
                break;
            default:
                break;
        }
        //-1的时候表示这是路径的最后一段了，没有第二次走了
        if(points[1] != -1){
            //得出方向,正在行走方向减去将要转的方向
            int i = directions[from-65][points[0]] - directions[points[0]][points[1]];
            switch (i){
                case -3:
                    direction = 2;   //左转
                    break;
                case -2:
                    direction = 3;   //后转
                    break;
                case -1:
                    direction = 1;   //右转
                    break;
                case 0:
                    direction = 4;   //直走
                    break;
                case 1:
                    direction = 2;   //左转
                    break;
                case 2:
                    direction = 3;   //后转
                    break;
                case 3:
                    direction = 1;   //右转
                    break;
                default:
                    direction = 0;   //不震动
                    break;
            }
        }else {
            direction = 0;
        }
    }

    /**
     * 弗若伊德算法，计算图中每两点的最短路径
     * @param map 地图的邻接矩阵
     */
    private static void Floyd(double[][] map){
        int i, j, k;

        for(i = 0; i<length; i++)
            for(j = 0; j<length;j++){
                edgeLength[i][j] = map[i][j];
                if(i!=j && map[i][j]!=INF)
                    Path[i][j] = i;
                else
                    Path[i][j] = -1;
            }
        for(k = 0; k<length; k++){
            for (i=0; i<length; i++)
                for(j=0; j<length; j++)
                    if(edgeLength[i][j] > edgeLength[i][k]+edgeLength[k][j]){
                        edgeLength[i][j] = edgeLength[i][k] + edgeLength[k][j];
                        Path[i][j] = Path[k][j];
                    }
        }
    }

    /**
     * 根据弗若伊德算法计算的结果，推算出起点到终点的前两个点
     * @param from
     * @param to
     * @return
     */
    private static int[] getTwoPoints(int from, int to){
        int[] places = new int[2];
        int[] apath = new int[length];
        if(edgeLength[from][to]!=INF && from!=to){
            int k = Path[from][to];
            int d = 0;
            apath[d] = to;              //加上起点
            while (k!=-1 && k!=from){   //路径上添加中间点
                d++;
                apath[d] = k;
                k = Path[from][k];
            }
            d++; apath[d] = from;      //加上终点
            //已经生成一条路径.反向存在数组apath中
            places[0] = apath[d-1];
            if(d-2 < 0){
                places[1] = -1;
            }else {
                places[1] = apath[d-2];
            }
        }
        return places;
    }
}
